package com.photoeditor.demo.ui.activity;

import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.widget.CircularProgressDrawable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.common.base.log.DLog;
import com.common.base.utils.DeviceUtils;
import com.common.base.utils.thread.ThreadPool;
import com.google.firebase.ml.vision.face.FirebaseVisionFace;
import com.gyf.barlibrary.ImmersionBar;
import com.ox.exif.Exif;
import com.photoeditor.R;
import com.photoeditor.demo.app.XActivity;
import com.photoeditor.demo.imageloader.GlideApp;
import com.photoeditor.demo.model.image.util.ImageHelper;
import com.photoeditor.demo.model.mlkit.ImageFaceDetector;
import com.photoeditor.demo.statistics.StatisticsConstant;
import com.photoeditor.demo.statistics.StatisticsUtils;
import com.photoeditor.demo.ui.widget.CenterAlignImageSpan;
import com.photoeditor.demo.ui.widget.face.TransformableImageView;
import com.photoeditor.demo.util.BitmapDecoder;
import com.photoeditor.demo.util.FontUtil;
import com.photoeditor.demo.util.Utils;
import com.photoeditor.demo.util.face.FaceUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

import static com.photoeditor.demo.model.face.FaceConstant.EXTRA_FROM;
import static com.photoeditor.demo.model.face.FaceConstant.PATH_PHOTO;
import static com.photoeditor.demo.ui.activity.BabyMainActivity.ACTION_PREDICT_BABY_FATHER;
import static com.photoeditor.demo.ui.activity.BabyMainActivity.ACTION_PREDICT_BABY_MOTHER;
import static com.photoeditor.demo.ui.activity.BabyMainActivity.RESULT_CODE_ADJUST_PHOTO_FATHER;
import static com.photoeditor.demo.ui.activity.BabyMainActivity.RESULT_CODE_ADJUST_PHOTO_MOTHER;


/**
 * @author lyzirving
 *         time        2018/10/30
 *         email       lyzirving@sina.com
 *         information
 */

public class FaceAdjustActivity extends XActivity implements View.OnClickListener
        , ImageFaceDetector.OnImageFaceDetectListener
        , TransformableImageView.FaceRefreshListener {

    public static final String TAG = FaceAdjustActivity.class.getSimpleName();
    public static final String EXTRA_ACTION = "EXTRA_ACTION";
    public static final String EXTRA_OUTPUTPATH_YOU = "EXTRA_OUTPUTPATH_YOU";
    public static final String EXTRA_OUTPUTPATH_YOU_NON_CIRCLE = "EXTRA_OUTPUTPATH_YOU_NON_CIRCLE";
    public static final String EXTRA_IS_FROM_ALBUM = "EXTRA_IS_FROM_ALBUM";
    public static final String EXTRA_IS_BACK_CAMERA = "EXTRA_IS_BACK_CAMERA";
    public static final String EXTRA_IS_FROM_FAKE_REPORT = "EXTRA_IS_FROM_FAKE_REPORT";
    public static final String EXTRA_FACE_RECT_YOU = "EXTRA_FACE_RECT_YOU";
    public static final String EXTRA_IMG_PATH = "EXTRA_IMG_PATH";
    public static final String SUFFIX_YOU = "_you.jpg";
    public static final String SUFFIX_PARTNER = "_partner.jpg";
    public static final String SUFFIX_NORMAL = ".jpg";
    public static final float MASK_RADIUS_SCREEN_RATIO = 256 * 1f / 360;
    public static final float MASK_RADIUS_SIZE_RATIO = 256 * 1f / 300;
    public static int sEdge = DeviceUtils.dip2px(5);
    public static final float SHARE_AREA_THRESHOLD_LOW = 0.3f;
    public static final float SHARE_AREA_THRESHOLD = 0.75f;
    public static final float SHARE_AREA_MIN_THRESHOLD = 0.17f;
    public static final long TIME_CLICK_INTERVAL = 500;
    public static final float CAMERA_PORTRAIT_RATIO = 3f / 4f;// width : height

    private RelativeLayout mLayoutAdjust;
    private RelativeLayout mLayoutAdjustBtnPanel;
    private TransformableImageView mAdjustView;
    private ImageView mFaceMaskView;
    private ImageView mBtnBack;
    private TextView mTvUserTxt;
    private ImageView mBtnDone;
    private ImageView mBtnCancel;
    private ImageView mBtnRotate;
    private TextView mTvTip;
    private ImageView mLoadingView;
    private TextView mIvMomDadFlag;

    private CircularProgressDrawable mProgressDrawable;
    private int mFaceMaskHeight;
    private Rect mFaceMaskRect;//用于生成裁减后的图片
    /** mask的近似区域 **/
    private Path mFaceMaskPath = new Path();
    /** 可见区域 **/
    private Path mFaceVisualPath = new Path();
    /** 用于辅助计算mask与人脸的面积 **/
    private Region mIntersectRegion = new Region();
    private Region mIntersectHelpRegion = new Region();
    private String mImgPath;
    private String mOutputPathYou;
    private String mOutputPathYouNonCircle;
    private String mOutputPathPartner;
    private String mOutputPathPartnerNonCircle;

    private long mLastTimeClickTotate;
    private String mAction;
//    private FaceRectView mDrawFaceView;
    private FaceHolder mCurSelectFace;

    private int mFrom;
    private boolean mIsInit;
    private long mEnterTime;

    private int mLayoutAdjustWidth;
    private int mLayoutAdjustHeight;
    private RectF mFaceRectYou;
    private RectF mFaceRectPartner;

    private boolean mIsBackCamera;

    private boolean mIsFromAlbum;

    private SoftReference<Bitmap> mOrigiBmpRef;

    private ImageFaceDetector mImageFaceDetector = new ImageFaceDetector();

    private boolean mIsFromFakeReport = false;

    private DialogInterface.OnClickListener mOnExitClickListener = new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
//            MainActivity.startMainActivityClearTop(FaceAdjustActivity.this);
        }
    };

    public static void startFaceAdjustActivity(Activity context, String imgPath, String action, int from, boolean isBackCamera) {
        if (imgPath == null || imgPath.equals("")) {
            return;
        }
        Intent intent = new Intent(context, FaceAdjustActivity.class);
        intent.putExtra(EXTRA_IMG_PATH, imgPath);
        intent.putExtra(EXTRA_ACTION, action);
        intent.putExtra(EXTRA_IS_BACK_CAMERA, isBackCamera);
        intent.putExtra(EXTRA_FROM, from);
        context.startActivity(intent);
    }
//
//    public static void startFaceAdjustActivityFromFakeReport(Activity context, String imgPath, String action, int from, boolean isBackCamera) {
//        if (imgPath == null || imgPath.equals("")) {
//            return;
//        }
//        Intent intent = new Intent(context, FaceAdjustActivity.class);
//        intent.putExtra(EXTRA_IMG_PATH, imgPath);
//        intent.putExtra(EXTRA_ACTION, action);
//        intent.putExtra(EXTRA_IS_BACK_CAMERA, isBackCamera);
//        intent.putExtra(FaceScanActivity.EXTRA_FROM, from);
//        intent.putExtra(EXTRA_IS_FROM_FAKE_REPORT, true);
//        context.startActivity(intent);
//    }
//
//    public static void startFaceAdjustActivity(Activity context, String imgPath, String outputPathYou
//            , String outputPathYouNonCircle, RectF face, String action, int from, boolean isBackCamera) {
//        if (imgPath == null || imgPath.equals("")) {
//            return;
//        }
//        Intent intent = new Intent(context, FaceAdjustActivity.class);
//        intent.putExtra(EXTRA_IMG_PATH, imgPath);
//        intent.putExtra(EXTRA_FACE_RECT_YOU, face);
//        intent.putExtra(EXTRA_ACTION, action);
//        intent.putExtra(EXTRA_OUTPUTPATH_YOU, outputPathYou);
//        intent.putExtra(EXTRA_OUTPUTPATH_YOU_NON_CIRCLE, outputPathYouNonCircle);
//        intent.putExtra(FaceScanActivity.EXTRA_FROM, from);
//        intent.putExtra(EXTRA_IS_BACK_CAMERA, isBackCamera);
//        context.startActivity(intent);
//    }
//
    public static void startFaceAdjustActivity(Activity context, Uri imgUri, String action, int from, boolean isBackCamera,
                                               boolean isFromAlbum, int requestCode) {
        if (imgUri == null) {
            return;
        }
        Intent intent = new Intent(context, FaceAdjustActivity.class);
        intent.setData(imgUri);
        intent.putExtra(EXTRA_ACTION, action);
        intent.putExtra(EXTRA_IS_BACK_CAMERA, isBackCamera);
        intent.putExtra(EXTRA_IS_FROM_ALBUM, isFromAlbum);
        intent.putExtra(EXTRA_FROM, from);
        context.startActivityForResult(intent, requestCode);
    }
//
//    public static void startFaceAdjustActivity(Activity context, Uri imgUri, String outputPathYou
//            , String outputPathYouNonCircle, RectF face, String action, int from, boolean isBackCamera) {
//        if (imgUri == null) {
//            return;
//        }
//        Intent intent = new Intent(context, FaceAdjustActivity.class);
//        intent.setData(imgUri);
//        intent.putExtra(EXTRA_FACE_RECT_YOU, face);
//        intent.putExtra(EXTRA_ACTION, action);
//        intent.putExtra(EXTRA_OUTPUTPATH_YOU, outputPathYou);
//        intent.putExtra(EXTRA_OUTPUTPATH_YOU_NON_CIRCLE, outputPathYouNonCircle);
//        intent.putExtra(FaceScanActivity.EXTRA_FROM, from);
//        intent.putExtra(EXTRA_IS_BACK_CAMERA, isBackCamera);
//        context.startActivity(intent);
//    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_face_adjust);
        ImmersionBar.with(this)
                .transparentStatusBar()
                .init();
        parseIntent();
        initView();
        preApplyImg();

        mImageFaceDetector.setListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mIsInit) {//activity回到栈顶时调用onResume，此时onResume时，mAdjustView的onLayout不需要初始化内部元素
            mAdjustView.setBackToStackTop(true);
        } else {
            mIsInit = true;
        }
        mEnterTime = System.currentTimeMillis();
        statisticFunShow();
    }

    @Override
    public void onBackPressed() {
        onClick(mBtnBack);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.icon_back:
                finish();
                break;
            case R.id.btn_adjust_cancel:
//                FaceScanEntranceStatisticsManager.setEntrace(FaceScanEntranceStatisticsManager.ENTRACE_OHTER);
//                if (mAction.equals(ACTION_PREDICT_BABY_MOTHER) || mAction.equals(ACTION_BEAUTY_CONTEST_RIVAL)) {
//                    FaceScanActivity.startFaceScanActivity(FaceAdjustActivity.this
//                            , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                } else {
//                    FaceScanActivity.startFaceScanActivityClearTop(FaceAdjustActivity.this, mAction);
//                }
//                EventBus.getDefault().post(new FaceAdjustReturnEvent());
                break;
            case R.id.btn_adjust_rotate:
                long curTime = System.currentTimeMillis();
                if (curTime - mLastTimeClickTotate >= TIME_CLICK_INTERVAL) {
                    boolean rotateFace = false;
                    if (mFaceRect != null || mFaceRectList != null) rotateFace = true;
                    mAdjustView.rotateAtSpecifiedAngle(TransformableImageView.ROTATE_ANGLE_90, rotateFace);
                    mLastTimeClickTotate = curTime;
                    restartDetectFace();
                }
                break;
            case R.id.btn_adjust_done:
                if (!checkFaceDetectResult()) {
                    break;
                }
                mAdjustView.setCanTouch(false);
                getSaveClipImageTask().execute();
                break;
            default:
                break;
        }
    }

    private AsyncTask<Void, Void, Boolean> getSaveClipImageTask() {
        return new AsyncTask<Void, Void, Boolean>() {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                showLoadingView(true);
            }

            @Override
            protected Boolean doInBackground(Void... voids) {
                Boolean isSuccess = saveClippedBitmap();
                return isSuccess;
            }

            @Override
            protected void onPostExecute(Boolean aBoolean) {
                super.onPostExecute(aBoolean);
                if (FaceAdjustActivity.this.isFinishing()) {
                    return;
                }
                showLoadingView(false);
                mAdjustView.setCanTouch(true);
                statisticDoneBtn(aBoolean.booleanValue());
                if (aBoolean.booleanValue()) {
                    doNextStep();
                } else {
                    FaceUtil.showExitDialog(FaceAdjustActivity.this,
                            getString(R.string.save_img_error),
                            mOnExitClickListener,
                            null,
                            null);
                }
            }
        };
    }

    private void statisticDoneBtn(boolean isSuccess) {
        switch (mAction) {
            case ACTION_PREDICT_BABY_FATHER:
                
                break;
            case ACTION_PREDICT_BABY_MOTHER:
               
                break;
        }
    }

    private void doNextStep() {
//        switch (mAction) {
//            case ACTION_PREDICT_BABY_FATHER:
//                FaceScanEntranceStatisticsManager.setEntrace(FaceScanEntranceStatisticsManager.sScaningEntrace);
//                FaceScanActivity.startFaceScanActivity(FaceAdjustActivity.this
//                        , ACTION_PREDICT_BABY_MOTHER, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_BEAUTY_CONTEST_YOU:
//                FaceScanEntranceStatisticsManager.setEntrace(FaceScanEntranceStatisticsManager.sScaningEntrace);
//                FaceScanActivity.startFaceScanActivity(FaceAdjustActivity.this
//                        , ACTION_BEAUTY_CONTEST_RIVAL, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_PREDICT_BABY_MOTHER:
//            case ACTION_BEAUTY_CONTEST_RIVAL:
//                ScanningActivity.startDoubleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle,
//                        mOutputPathPartner, mOutputPathPartnerNonCircle, mFaceRectYou,
//                        mFaceRectPartner, mFrom);
//                break;
//            case ACTION_ETHNIC:
//                if (mIsFromFakeReport) {
//                    //
//                    ScanningActivityCopy.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                            , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                    break;
//                }
//            case ACTION_PREDICT_FUTURE:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//            case ACTION_AGE_CAMERA:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_EXOTIC_BLEND:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_GENDER_SWITCH:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_PREVIOUS_LIFE:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_AGING_SCANNER:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//            case ACTION_KID_FACE:
//                ScanningActivity.startSingleScanningFaceAnimation(FaceAdjustActivity.this
//                        , mAction, mOutputPathYou, mOutputPathYouNonCircle, mFaceRectYou, mFrom);
//                break;
//        }
        Intent intent = new Intent();
        switch (mAction) {
            case ACTION_PREDICT_BABY_FATHER:
                intent.putExtra(EXTRA_IMG_PATH, mOutputPathYou);
                setResult(RESULT_CODE_ADJUST_PHOTO_FATHER, intent);
                break;
            case ACTION_PREDICT_BABY_MOTHER:
                intent.putExtra(EXTRA_IMG_PATH, mOutputPathPartner);
                setResult(RESULT_CODE_ADJUST_PHOTO_MOTHER, intent);
                break;
        }
        finish();
    }

    private void initView() {
        mLayoutAdjust = findViewById(R.id.layout_face_adjust);
        mLayoutAdjustBtnPanel = findViewById(R.id.layout_face_adjust_btns);
        mAdjustView = findViewById(R.id.adjust_view);
        mFaceMaskView = findViewById(R.id.face_mask_view);
//        if (TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
//            mFaceMaskView.setVisibility(View.GONE);
//        }
        mBtnBack = findViewById(R.id.icon_back);
        mTvUserTxt = findViewById(R.id.user_txt);
        mBtnRotate = findViewById(R.id.btn_adjust_rotate);
        mBtnCancel = findViewById(R.id.btn_adjust_cancel);
        mBtnDone = findViewById(R.id.btn_adjust_done);
        mTvTip = findViewById(R.id.tv_adjust);
        mLoadingView = findViewById(R.id.img_progress);
//        mDrawFaceView = findViewById(R.id.view_draw_face);
        mIvMomDadFlag = findViewById(R.id.mom_dad_flag);

        mBtnBack.setOnClickListener(this);
        mBtnRotate.setOnClickListener(this);
        mBtnCancel.setOnClickListener(this);
        mBtnDone.setOnClickListener(this);

        mProgressDrawable = new CircularProgressDrawable(FaceAdjustActivity.this);
        mProgressDrawable.setStrokeWidth(DeviceUtils.dip2px(2));
        mProgressDrawable.setColorSchemeColors(getResources().getColor(R.color.progress_stroke_color));
        mLoadingView.setImageDrawable(mProgressDrawable);

        FontUtil.setCustomFontMedium(mTvUserTxt);
        mAdjustView.setCanRotateByFinger(false);
        mAdjustView.addFaceRefreshListener(this);
        mAdjustView.setCanTouch(false);
        showLoadingView(true);

        setUserTitle();

        adjustViewHeight();
    }

    private void statisticFunShow() {
        switch (mAction) {
            case ACTION_PREDICT_BABY_FATHER:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_BABY,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_YOU_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        StatisticsUtils.getStatisticsParkingType(mEnterTime),
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_BABY,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
                break;
            case ACTION_PREDICT_BABY_MOTHER:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_BABY,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_YOU_PAR_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        StatisticsUtils.getStatisticsParkingType(mEnterTime),
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_2_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_BABY,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
                break;
//            case ACTION_AGE_CAMERA:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_VALUE_AGING,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        StatisticsUtils.getStatisticsParkingType(mEnterTime),
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_AGING,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
//            case ACTION_PREDICT_FUTURE:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PREDICTOR,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                break;
//            case ACTION_ETHNIC:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_ETHNIC,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_ETHNICITY,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
//            case ACTION_EXOTIC_BLEND:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_EXOTIC,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_EXOTIC,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
//            case ACTION_GENDER_SWITCH:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_GENDER_SWITCH,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_GENDER,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
//            case ACTION_BEAUTY_CONTEST_YOU:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_BEAUTY,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_YOU_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                break;
//            case ACTION_BEAUTY_CONTEST_RIVAL:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_BEAUTY,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_YOU_PAR_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                break;
//            case ACTION_PREVIOUS_LIFE:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PREVIOUS_LIFE,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_PAST_LIFE,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
//            case ACTION_AGING_SCANNER:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_AGING_SCANNER,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_AGE_SCAN,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
//            case ACTION_KID_FACE:
//                StatisticsUtils.statisticsFaceSecret(StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_KID_FACE,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_PIC_ADJ,
//                        StatisticsConstant.STATISTIC_EVENT_FUN_VALUE_SHOW,
//                        FaceScanEntranceStatisticsManager.sScaningEntrace);
//                StatisticsUtils.statisticGrowingIo(StatisticsConstant.EVENT_PIC_ADJ_1_SHOW,
//                        StatisticsConstant.KEY_ALL_FUN, StatisticsConstant.ALL_FUN_VALUE_KID_FACE,
//                        StatisticsConstant.KEY_PIC_ADJ_ENTR,
//                        mIsFromAlbum ? StatisticsConstant.PIC_ADJ_ENTR_VALUE_ALBUM : StatisticsConstant.PIC_ADJ_ENTR_VALUE_SHOOT);
//                break;
            default:
                break;
        }
    }

    private void adjustViewHeight() {
        //调整照片高度，与FaceScanActivity的camera preview保持一致
        int cameraViewHeight = (int) (DeviceUtils.getScreenWidthPx() / CAMERA_PORTRAIT_RATIO);
        ViewGroup.LayoutParams lp = mLayoutAdjust.getLayoutParams();
        lp.width = DeviceUtils.getScreenWidthPx();
        lp.height = cameraViewHeight;
        mLayoutAdjust.setLayoutParams(lp);
        mLayoutAdjustWidth = DeviceUtils.getScreenWidthPx();
        mLayoutAdjustHeight = cameraViewHeight;

        //底部button panel height
        int bottomPanelHeight;
//        if (!TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
            bottomPanelHeight = DeviceUtils.getScreenHeightPx() - cameraViewHeight;
//        } else {
//            bottomPanelHeight = DeviceUtils.getScreenHeightPx() - (DeviceUtils.getScreenWidthPx() + DeviceUtils.dip2px(72));
//        }
        lp = mLayoutAdjustBtnPanel.getLayoutParams();
        lp.height = bottomPanelHeight;
        mLayoutAdjustBtnPanel.setLayoutParams(lp);

        //遮罩的高度
        mFaceMaskHeight = DeviceUtils.getScreenHeightPx() - DeviceUtils.dip2px(72) - bottomPanelHeight;
        createFaceMaskRect();

        //底部tip文字的显示位置
        Paint.FontMetrics fm = mTvTip.getPaint().getFontMetrics();
        mTipHeight = (int) (fm.bottom - fm.top);
        RelativeLayout.LayoutParams rllp = (RelativeLayout.LayoutParams) mTvTip.getLayoutParams();
//        if (TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
//            rllp.bottomMargin = (cameraViewHeight - mFaceMaskRect.bottom) / 2 - mTipHeight / 2 + (cameraViewHeight - ((DeviceUtils.getScreenWidthPx() + DeviceUtils.dip2px(72))));
//        } else {
            rllp.bottomMargin = (cameraViewHeight - mFaceMaskRect.bottom) / 2 - mTipHeight / 2;
//        }

        //调整旋转按钮位置，防止其被tip文字遮挡
        rllp = (RelativeLayout.LayoutParams) mBtnRotate.getLayoutParams();
        rllp.bottomMargin = (cameraViewHeight - mFaceMaskRect.bottom) / 2 + mTipHeight / 2 + DeviceUtils.dip2px(10);
    }

    private void createFaceMaskRect() {
        mFaceMaskRect = new Rect();
        int maskRadius = (int) ((DeviceUtils.getScreenWidthPx() / 2) * MASK_RADIUS_SCREEN_RATIO / MASK_RADIUS_SIZE_RATIO);
        int left = (DeviceUtils.getScreenWidthPx() / 2) - maskRadius;
        int top = DeviceUtils.dip2px(72) + mFaceMaskHeight / 2 - maskRadius;
        mFaceMaskRect.set(left, top, left + 2 * maskRadius, top + 2 * maskRadius);

        mFaceMaskPath.reset();
        // 先移到顶部中心点，顺时针添加点，组成一个近似人脸mask的区域
        mFaceMaskPath.moveTo(DeviceUtils.getScreenWidthPx() / 2, top);
        mFaceMaskPath.quadTo(mFaceMaskRect.right + maskRadius * 2 / 3, top + maskRadius,
                DeviceUtils.getScreenWidthPx() / 2, mFaceMaskRect.bottom);
        mFaceMaskPath.quadTo(mFaceMaskRect.left - maskRadius * 2 / 3, top + maskRadius,
                DeviceUtils.getScreenWidthPx() / 2, top);

        int firstX = 0, firstY = DeviceUtils.dip2px(72);
        int secondX = DeviceUtils.getScreenWidthPx(), secondY = firstY;
        int thirdX = secondX, thirdY = secondY + mFaceMaskHeight;
        int forthX = firstX, forthY = thirdY;
        mFaceVisualPath.reset();
        mFaceVisualPath.moveTo(firstX, firstY);
        mFaceVisualPath.lineTo(secondX, secondY);
        mFaceVisualPath.lineTo(thirdX, thirdY);
        mFaceVisualPath.lineTo(forthX, forthY);
        mFaceVisualPath.lineTo(firstX, firstY);
        // test：屏幕上绘制mFaceMaskPath区域
//        FaceRectView view = new FaceRectView(this);
//        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//        ((ViewGroup)findViewById(R.id.layout_face_adjust).getParent()).addView(view, layoutParams);
//        view.setPath(mFaceVisualPath);
    }

    private void setUserTitle() {
        switch (mAction) {
//            case ACTION_BEAUTY_CONTEST_RIVAL:
//                mTvUserTxt.setText(getString(R.string.text_rival));
//                mIvMomDadFlag.setText(R.string.dad);
//                mIvMomDadFlag.setBackgroundResource(R.drawable.bg_shape_flag_dad);
//                mIvMomDadFlag.setVisibility(View.VISIBLE);
//                break;
            case ACTION_PREDICT_BABY_MOTHER:
                mTvUserTxt.setText(getString(R.string.baby_prediction));
                mIvMomDadFlag.setText(R.string.mom);
                mIvMomDadFlag.setBackgroundResource(R.drawable.bg_shape_flag_mom);
                mIvMomDadFlag.setVisibility(View.VISIBLE);
                break;
//            case ACTION_AGE_CAMERA:
//                mTvUserTxt.setText(R.string.age_camera);
//                break;
//            case ACTION_ETHNIC:
//                mTvUserTxt.setText(R.string.ethnicity_analyzer);
//                break;
//            case ACTION_PREDICT_FUTURE:
//                mTvUserTxt.setText(R.string.future_predictor);
//                break;
//            case ACTION_EXOTIC_BLEND:
//                mTvUserTxt.setText(R.string.exotic_blend);
//                break;
//            case ACTION_PREVIOUS_LIFE:
//                mTvUserTxt.setText(R.string.previous_life);
//                break;
//            case ACTION_GENDER_SWITCH:
//                mTvUserTxt.setText(R.string.gender_switch);
//                break;
//            case ACTION_AGING_SCANNER:
//                mTvUserTxt.setText(R.string.aging_scanner);
//                break;
//            case ACTION_KID_FACE:
//                mTvUserTxt.setText(R.string.kid_face);
//                break;
            default:
                mTvUserTxt.setText(getString(R.string.baby_prediction));
                mIvMomDadFlag.setText(R.string.dad);
                mIvMomDadFlag.setBackgroundResource(R.drawable.bg_shape_flag_dad);
                mIvMomDadFlag.setVisibility(View.VISIBLE);
                break;
        }
    }

    private void parseIntent() {
        Intent intent = getIntent();
        mIsFromFakeReport = intent.getBooleanExtra(EXTRA_IS_FROM_FAKE_REPORT, false);
        mImgPath = intent.getStringExtra(EXTRA_IMG_PATH);
        mAction = intent.getStringExtra(EXTRA_ACTION);
//        if (mAction != null &&
//                (mAction.equals(ACTION_PREDICT_BABY_MOTHER) || mAction.equals(ACTION_BEAUTY_CONTEST_RIVAL))) {
        if (TextUtils.equals(mAction, ACTION_PREDICT_BABY_MOTHER)) {
            mOutputPathYou = intent.getStringExtra(EXTRA_OUTPUTPATH_YOU);
            mOutputPathYouNonCircle = intent.getStringExtra(EXTRA_OUTPUTPATH_YOU_NON_CIRCLE);
            mFaceRectYou = intent.getParcelableExtra(EXTRA_FACE_RECT_YOU);
        }
        mFrom = intent.getIntExtra(EXTRA_FROM, 0);
        mIsBackCamera = intent.getBooleanExtra(EXTRA_IS_BACK_CAMERA, false);
        mIsFromAlbum = intent.getBooleanExtra(EXTRA_IS_FROM_ALBUM, false);
    }

    private void preApplyImg() {
        Uri data = getIntent().getData();
        if (data != null && TextUtils.isEmpty(mImgPath)) {
            ThreadPool.runOnNonUIThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), getIntent().getData());
                        if (bitmap != null && !bitmap.isRecycled()) {
                            String path = PATH_PHOTO + File.separator + System.currentTimeMillis() + ".jpg";
                            ImageHelper.saveBitmapToSdcard(path, bitmap);
                            mImgPath = path;
                        }
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                applyImg();
                            }
                        });
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        } else {
            applyImg();
        }
    }

    private void applyImg() {
        if (FaceAdjustActivity.this.isDestroyed()) {
            return;
        }
//        GlideApp.with(FaceAdjustActivity.this).load(mImgPath).listener(new RequestListener<Drawable>() {
//            @Override
//            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
//                return false;
//            }
//
//            @Override
//            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
//                startDetectFace();
//                return false;
//            }
//        }).into(mAdjustView);
        GlideApp.with(FaceAdjustActivity.this).asBitmap().load(mImgPath).into(new SimpleTarget<Bitmap>() {
            @Override
            public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                mAdjustView.setImageBitmap(resource);
                startDetectFace();
            }
        });
    }

    ViewTreeObserver.OnDrawListener mOnDrawListener;
    private boolean mIsDetecting = false;
    private float mBoundingBoxScale = 1;//用于记录被缩放的图片，人脸框需用该值进行还原
    private void startDetectFace() {
        if (mImageFaceDetector == null) {
            return ;
        }
        if (mOnDrawListener == null) {
            mOnDrawListener = new ViewTreeObserver.OnDrawListener() {
                @Override
                public void onDraw() {
                    if (mAdjustView == null || mAdjustView.getDrawable() == null) {
                        return;
                    }
                    ThreadPool.runUITask(new Runnable() {
                        @Override
                        public void run() {
                            mAdjustView.getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
                        }
                    });
                    if (mIsDetecting) {
                        return;
                    }
                    mIsDetecting = true;
                    ThreadPool.runOnNonUIThread(new Runnable() {
                        @Override
                        public void run() {
                            Bitmap cache = getBitmapOnScreen();
                            if (cache == null || cache.isRecycled() || cache.getWidth() <= 0 || cache.getHeight() <= 0) {
                                //错误处理
                                processDetectFaceResult(null);
                                return;
                            }
                            Bitmap detectImg = BitmapDecoder.scaleBitmap4Detect(cache);
                            if (detectImg == null || detectImg.isRecycled() || detectImg.getWidth() <= 0 || detectImg.getHeight() <= 0) {
                                //错误处理
                                processDetectFaceResult(null);
                                return;
                            }
                            mBoundingBoxScale = (float) detectImg.getWidth() / cache.getWidth();
                            detectFaceAsync(detectImg);
                        }
                    }, 500);
                }
            };
            mAdjustView.getViewTreeObserver().addOnDrawListener(mOnDrawListener);
        }
    }

    private void restartDetectFace() {
        mOnDrawListener = null;
        mIsDetecting = false;
        startDetectFace();
    }

    /**
     * 异步对图片进行人脸检测
     */
    private void detectFaceAsync(Bitmap bitmap) {
        mImageFaceDetector.startDetect(bitmap);
    }

    private String getImgSuffix() {
        if (mAction != null && mAction.equals(ACTION_PREDICT_BABY_FATHER)) {
            return SUFFIX_YOU;
        } else if (mAction != null && mAction.equals(ACTION_PREDICT_BABY_MOTHER)) {
            return SUFFIX_PARTNER;
        } else {
            return SUFFIX_NORMAL;
        }
    }

    private void showLoadingView(boolean show) {
        if (show && mProgressDrawable != null && mLoadingView != null) {
            mLoadingView.setVisibility(View.VISIBLE);
            mProgressDrawable.start();
        } else if (mProgressDrawable != null && mLoadingView != null){
            mLoadingView.setVisibility(View.INVISIBLE);
            mProgressDrawable.stop();
        }
    }

    private void generateBmpRef() {
        mOrigiBmpRef = null;
        Bitmap compressed;
//        if (TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
            compressed = ImageHelper.getOptimalBitmapFromPath(mImgPath, 400, 1500);
//        } else {
            compressed = ImageHelper.getOptimalBitmapFromPath(mImgPath, 200, 1500);
//        }

        if (compressed == null) return;

        if (mIsBackCamera) {//后置摄像头拍照需要处理
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            compressed.compress(Bitmap.CompressFormat.JPEG, 100, os);
            int rotation = Exif.getOrientation(os.toByteArray());
            if (rotation != 90) {
                Matrix rotateMatrix = new Matrix();
                float degree = 90;
                switch (rotation) {
                    case 0:
                        degree = 90;
                        break;
                    case 180:
                        degree = -90;
                        break;
                    case 270:
                        degree = 180;
                        break;
                }
                rotateMatrix.setRotate(degree);
                try {
                    compressed = Bitmap.createBitmap(compressed, 0, 0, compressed.getWidth(),
                            compressed.getHeight(), rotateMatrix, true);
                    os.close();
                } catch (OutOfMemoryError error) {
                    error.printStackTrace();
                    System.gc();
                    return;
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }
            } else {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
        mOrigiBmpRef = new SoftReference<>(compressed);
    }

    private Bitmap getBitmapOnScreen() {
        if (mOrigiBmpRef == null || mOrigiBmpRef.get() == null || mOrigiBmpRef.get().isRecycled()) {
            generateBmpRef();
        }
        if (mOrigiBmpRef == null || mOrigiBmpRef.get() == null) return null;
        Bitmap cache = mOrigiBmpRef.get();
        Bitmap backgroundBmp, transformedTmp;
        try {
            backgroundBmp = Bitmap.createBitmap(mLayoutAdjustWidth, mLayoutAdjustHeight, Bitmap.Config.ARGB_4444);
        } catch (OutOfMemoryError error) {
            error.printStackTrace();
            System.gc();
            return null;
        }
        RectF dstBounds = new RectF(mAdjustView.getDrawable().getBounds());
        Matrix transformableMatrix = mAdjustView.getTransformableMatrix();
        transformableMatrix.mapRect(dstBounds, dstBounds);
        try {
            transformedTmp = Bitmap.createBitmap(cache, 0, 0, cache.getWidth(),
                    cache.getHeight(), transformableMatrix, true);
        } catch (OutOfMemoryError error) {
            error.printStackTrace();
            System.gc();
            return null;
        }
        if (backgroundBmp == null) return null;
        if (transformedTmp == null) return null;

        Canvas canvas = new Canvas(backgroundBmp);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        canvas.drawBitmap(transformedTmp, null, dstBounds, paint);

        if (transformedTmp != null && !transformedTmp.isRecycled()) transformedTmp.recycle();

        return backgroundBmp;
    }

    private boolean saveClippedBitmap() {
        try {
            String outputPath = PATH_PHOTO + File.separator + System.currentTimeMillis() + "_clip" + getImgSuffix();
            String outputPathNonCicle = PATH_PHOTO + File.separator + System.currentTimeMillis() + "_clip_no_cicle" + getImgSuffix();
            Bitmap tmpBitmap = getBitmapOnScreen();
            if (tmpBitmap == null || tmpBitmap.isRecycled()) return false;
            if (mFaceMaskRect == null) return false;
            Bitmap clippeddBmp = createClippedBitmap(tmpBitmap);
            Bitmap singleFaceBmp = createSingleFaceBmp(tmpBitmap, clippeddBmp);
            if (!ImageHelper.saveBitmapToSdcardInPNG(outputPathNonCicle, clippeddBmp)) {
                return false;
            }
            if (!ImageHelper.saveBitmapToSdcardInPNG(outputPath, singleFaceBmp)) {
                return false;
            }
            storeData(outputPath, outputPathNonCicle);
            if (clippeddBmp != null && !clippeddBmp.isRecycled()) clippeddBmp.recycle();
            if (singleFaceBmp != null && !singleFaceBmp.isRecycled()) singleFaceBmp.recycle();
            if (tmpBitmap != null && !tmpBitmap.isRecycled()) tmpBitmap.recycle();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private void storeData(String path, String pathNonCicle) {
//        if (TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
//            boolean isSingle = !(mFaceRectList != null && mFaceRectList.size() > 1);
//            mOutputPathYou = new String(path);
//            mOutputPathYouNonCircle = new String(pathNonCicle);
////            mFaceRectYou = new RectF(getFaceRect(isSingle));
//            mFaceRectYou = new RectF(0, DeviceUtils.dip2px(72), DeviceUtils.getScreenWidthPx(), DeviceUtils.dip2px(72) + mFaceMaskHeight);
//        } else {
//            boolean isSingle = !(mFaceRectList != null && mFaceRectList.size() > 1 && mCurSelectFace != null);
        boolean isSingle = true;
            //预测宝宝、选美，且调整partner(rival)的照片时，不给mOutputPathYou赋值
            if (TextUtils.equals(mAction, ACTION_PREDICT_BABY_FATHER)) {
                mOutputPathYou = new String(path);
                mOutputPathYouNonCircle = new String(pathNonCicle);
                mFaceRectYou = new RectF(getFaceRect(isSingle));
            } else if (TextUtils.equals(mAction, ACTION_PREDICT_BABY_MOTHER)) {
                mOutputPathPartner = new String(path);
                mOutputPathPartnerNonCircle = new String(pathNonCicle);
                mFaceRectPartner = new RectF(getFaceRect(isSingle));
            }
//        }
    }

    private Bitmap createSingleFaceBmp(Bitmap original, Bitmap clippedSrc) {
        Bitmap result = null;
//        if (mFaceRectList != null && mFaceRectList.size() > 1 && mCurSelectFace != null) {
//            //有多张人脸时，需裁出选中的人脸，且需保持位置
//            result = getSingleWhenMultipleFace(original);
//        } else {
            result = Bitmap.createBitmap(clippedSrc, 0, 0, clippedSrc.getWidth(), clippedSrc.getHeight());
//        }
        return result;
    }

    private Bitmap createClippedBitmap(Bitmap bmp) {
//        if (!TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
            return Bitmap.createBitmap(bmp, mFaceMaskRect.left - sEdge, mFaceMaskRect.top - sEdge,
                    mFaceMaskRect.width() + 2 * sEdge, mFaceMaskRect.height() + 2 * sEdge);
//        }
//        else {
//            int x = 0;
//            int y = DeviceUtils.dip2px(72);
//            int width = DeviceUtils.getScreenWidthPx();
//            int height = mFaceMaskHeight;
//            return Bitmap.createBitmap(bmp, x, y, width, height);
//        }
    }

    /**
     * 扩展人脸框的范围
     * @param src
     * @param limitLeft
     * @param limitTop
     * @param limitRight
     * @param limitBottom
     * @return
     */
    private Rect getOptimalFaceRect(Rect src, int limitLeft, int limitTop, int limitRight, int limitBottom) {
        int bound = Math.min(src.width(), src.height()) / 8;
        int left = src.left - bound;
        int top = src.top - bound;
        int right = src.right + bound;
        int bottom = src.bottom + bound;
        if (left < limitLeft) left = limitLeft;
        if (top < limitTop) top = limitTop;
        if (right > limitRight) right = limitRight;
        if (bottom > limitBottom) bottom = limitBottom;
        return new Rect(left, top, right, bottom);
    }

    private Bitmap getSingleWhenMultipleFace(Bitmap src) {
//        Bitmap result = null;
//        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
//        Rect srcFaceRect = getOptimalFaceRect(mCurSelectFace.faceRect,
//                mFaceMaskRect.left - sEdge,
//                mFaceMaskRect.top - sEdge,
//                mFaceMaskRect.right + sEdge,
//                mFaceMaskRect.bottom + sEdge);
//        Rect totalFaceRect = new Rect();
//        totalFaceRect.set(0, 0, srcFaceRect.width(), srcFaceRect.height());
//
//        Bitmap faceBmp = Bitmap.createBitmap(src, srcFaceRect.left, srcFaceRect.top, srcFaceRect.width(), srcFaceRect.height());
//
//        result = Bitmap.createBitmap(mFaceMaskRect.width() + 2 * sEdge
//                ,mFaceMaskRect.height() + 2 * sEdge, Bitmap.Config.ARGB_8888);
//        Rect dst = new Rect();
//        int left = srcFaceRect.left - (mFaceMaskRect.left - sEdge);
//        int top = srcFaceRect.top - (mFaceMaskRect.top - sEdge);
//        dst.set(left, top, left + totalFaceRect.width(), top + totalFaceRect.height());
//
//        Canvas drawResult = new Canvas(result);
//        drawResult.drawBitmap(faceBmp, totalFaceRect, dst, paint);
//        return result;
        return null;
    }

    private RectF getFaceRect(boolean isSingle) {
        RectF res = new RectF();
        Rect srcFaceRect = null;
        if (isSingle) {
            srcFaceRect = new Rect(mFaceRect);
        }
//        else {
//            srcFaceRect = new Rect(mCurSelectFace.faceRect);
//        }
        int left = srcFaceRect.left - (mFaceMaskRect.left - sEdge);
        int top = srcFaceRect.top - (mFaceMaskRect.top - sEdge);
        res.set(left, top, left + srcFaceRect.width(), top + srcFaceRect.height());
        return res;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mImageFaceDetector != null) {
            mImageFaceDetector.release();
            mImageFaceDetector = null;
        }
        if (mOrigiBmpRef != null) {
            if (mOrigiBmpRef.get() != null && !mOrigiBmpRef.get().isRecycled()) {
                mOrigiBmpRef.get().recycle();
            }
            mOrigiBmpRef = null;
        }
        showLoadingView(false);
        ImmersionBar.with(this).destroy();
    }

    private static final int DETECT_STATE_NO_STATE = 10;
    private static final int DETECT_STATE_NO_FACE = 11;
    private static final int DETECT_STATE_FACE_POSITION_ERROR = 12;
    private static final int DETECT_STATE_FACE_COUNT_ERROR = 13;
    private static final int DETECT_STATE_FACE_TOO_SMALL = 14;
    private static final int DETECT_STATE_READY = 15;
    private int mLastDetectState = DETECT_STATE_NO_STATE;
    private int mCurDetectState = DETECT_STATE_NO_STATE;
    private int mNewDetectState = DETECT_STATE_NO_STATE;
    private static final long TIP_SHOW_ANIM_TIME = 400;
    private ValueAnimator mTipShowAnimator;
    private int mTipHeight;
    private Rect mFaceRect;
    private List<Rect> mFaceRectList;

    private void processSingleFaceRect(Rect face) {
        boolean isInRequireRange = checkFaceRange(face);
        if (isInRequireRange) {
            DLog.d(TAG, "adjust one face success");
            processDetectResult(mNewDetectState);
            return;
        } else {
            DLog.d(TAG, "adjust one face error");
            processDetectResult(mNewDetectState);
            return;
        }
    }

    private void processMultipleFaceRect(List<Rect> faces) {
        FaceHolder faceHolder = getFaceNearestFromCenter(faces);
        if (faceHolder == null) {//多个人脸不满足条件
            DLog.d(TAG, "detect multiple face error");
            processDetectResult(mNewDetectState);
            return;
        }
        if (judgeIfHasMultipleFaceIntersectWithMask()) {
            DLog.d(TAG, "multiple face intersect with mask");
            processDetectResult(mNewDetectState);
            return;
        }
        //多张人脸中，有一张满足要求
        DLog.d(TAG, "detect multiple face success");
        processDetectResult(mNewDetectState);
        setCurSelectFaceFromMultipleFaces(faceHolder);
    }

    private SpannableString getEmjobString(int newState){
        Drawable drawable = getEmojiDrawable(newState);
        String str = getTipContent(newState);
        SpannableString sp = new SpannableString(str);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        //居中对齐imageSpan
        CenterAlignImageSpan imageSpan = new CenterAlignImageSpan(drawable);
        imageSpan.setYOffset(0);
        sp.setSpan(imageSpan, 0, 1, ImageSpan.ALIGN_BASELINE);
        return sp;
    }

    private Drawable getEmojiDrawable(int newState) {
        Drawable d = null;
        switch (newState) {
            case DETECT_STATE_READY:
                d = getResources().getDrawable(R.drawable.emoji_hook);
                break;
            case DETECT_STATE_NO_FACE:
                d = getResources().getDrawable(R.drawable.emoji_bang);
                break;
            case DETECT_STATE_FACE_COUNT_ERROR:
                d = getResources().getDrawable(R.drawable.emoji_bang);
                break;
            case DETECT_STATE_FACE_POSITION_ERROR:
                d = getResources().getDrawable(R.drawable.emoji_bang);
                break;
            case DETECT_STATE_FACE_TOO_SMALL:
                d = getResources().getDrawable(R.drawable.emoji_bang);
                break;
        }
        return d;
    }

    private String getTipContent(int newState) {
        String tip = null;
        switch (newState) {
            case DETECT_STATE_READY:
                tip = getString(R.string.tip_adjust_success);
                break;
            case DETECT_STATE_NO_FACE:
                tip = getString(R.string.tip_no_face);
                break;
            case DETECT_STATE_FACE_COUNT_ERROR:
                tip = getString(R.string.tip_error_face);
                break;
            case DETECT_STATE_FACE_POSITION_ERROR:
                tip = getString(R.string.tip_error_face);
                break;
            case DETECT_STATE_FACE_TOO_SMALL:
                tip = getString(R.string.tip_face_small);
                break;
        }
        return tip;
    }

    private void processDetectResult(int newState) {
        mCurDetectState = newState;
        SpannableString tip = getEmjobString(newState);
        if (isDetectStateChange()) {
            //showBottomTip会使mAdjustView重layout，此时layout中不需要执行初始化
            mAdjustView.setLayoutNotInit(true);
            showBottomTip(tip, true);
        }
        mLastDetectState = newState;
    }

    private void processDetectFaceResult(@NonNull List<FirebaseVisionFace> facesList) {
        //没人识别出人脸
        if (facesList == null || facesList.size() == 0) {
            DLog.d(TAG, "no face");
            mNewDetectState = DETECT_STATE_NO_FACE;
            processDetectResult(mNewDetectState);
            mFaceRectList = null;
            mFaceRect = null;
            return;
        }
        //人脸数量不等于1
        if (facesList.size() != 1) {
            DLog.d(TAG, "detect multiple face");
            setFaceRect(true, null, createFaceRectList(facesList));
            FaceHolder faceHolder = getFaceNearestFromCenter(mFaceRectList);
            if (faceHolder == null) {//多个人脸不满足条件
                DLog.d(TAG, "detect multiple face error");
                processDetectResult(mNewDetectState);
                return;
            }
            if (judgeIfHasMultipleFaceIntersectWithMask()) {
                DLog.d(TAG, "multiple face intersect with mask");
                processDetectResult(mNewDetectState);
                return;
            }
            //多张人脸中，有一张满足要求，选中该人脸
            processDetectResult(mNewDetectState);
            setCurSelectFaceFromMultipleFaces(faceHolder);
            return;
        }
        //一张人脸的情况
        if (facesList.size() == 1) {
            setFaceRect(false, adjustBoundingBox(facesList.get(0).getBoundingBox()), null);
            DLog.d(TAG, "face rect: " + mFaceRect);
            boolean isInRequireRange = checkFaceRange(mFaceRect);
            if (isInRequireRange) {
                DLog.d(TAG, "detect one face success");
                processDetectResult(mNewDetectState);
                return;
            } else {
                DLog.d(TAG, "detect one face error");
                processDetectResult(mNewDetectState);
                return;
            }
        }
    }

    private boolean judgeIfHasMultipleFaceIntersectWithMask() {
        int faceCountIntersectWithMask = 0;
        for (Rect face : mFaceRectList) {
            boolean isIntersect = isFaceIntersectWithMask(face);
            if (isIntersect) {
                faceCountIntersectWithMask++;
            }
            if (faceCountIntersectWithMask >= 2) {
                mNewDetectState = DETECT_STATE_FACE_COUNT_ERROR;
                return true;
            }
        }
        mNewDetectState = DETECT_STATE_READY;
        return false;
    }

    private boolean isFaceIntersectWithMask(Rect face) {
        if (!Rect.intersects(face, mFaceMaskRect)) {
            return false;
        }

//        mIntersectHelpRegion.set(face);
//        if (!TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
//            mIntersectRegion.setPath(mFaceMaskPath, mIntersectHelpRegion);
//        } else {
            mIntersectRegion.setPath(mFaceVisualPath, mIntersectHelpRegion);
//        }
        int area = Utils.calculateRegionArea(mIntersectRegion);
        if ((float)area / (face.width() * face.height()) > SHARE_AREA_THRESHOLD_LOW) {
            return true;
            /*if ((float)face.width() * face.height() / (mFaceMaskRect.width() * mFaceMaskRect.height()) > FaceScanActivity.SHARE_AREA_MIN_THRESHOLD) {
                // 人脸框太小，提示错误
                return true;
            }*/
        }
        return false;
    }

    /**
     * @param isMultipleFace 图中是否有多张人脸
     * @param face  坐标换算后的单张人脸
     * @param faceList  坐标换算后的多张人脸
     */
    private void setFaceRect(boolean isMultipleFace, Rect face, List<Rect> faceList) {
        if (isMultipleFace && face == null && faceList != null) {
            mFaceRect = null;
            mFaceRectList = faceList;
            mAdjustView.setFaceRectList(mFaceRectList);
//            mDrawFaceView.setFaceListRect(mFaceRectList);
            return;
        }
        if (!isMultipleFace && faceList == null && face != null) {
            mFaceRectList = null;
            mFaceRect = face;
            mAdjustView.setFaceRect(mFaceRect);
//            mDrawFaceView.setFaceRect(mFaceRect);
        }
    }

    private List<Rect> createFaceRectList(@NonNull List<FirebaseVisionFace> facesList) {
        List<Rect> list = new ArrayList<>();
        for (FirebaseVisionFace face : facesList) {
            DLog.d(TAG, "multiple face: " + face.getBoundingBox());
            list.add(adjustBoundingBox(face.getBoundingBox()));
        }
        return list;
    }

    private boolean checkFaceDetectResult() {
        if (mCurDetectState == DETECT_STATE_NO_STATE) return false;
        if (mCurDetectState != DETECT_STATE_READY) {
            showTipEnlargeTipAnim();
            return false;
        }
        return true;
    }

    private void showTipEnlargeTipAnim() {
        ValueAnimator enlarge = ValueAnimator.ofFloat(0, 1f);
        enlarge.setDuration(TIP_SHOW_ANIM_TIME);
        enlarge.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float ratio = animation.getAnimatedFraction();
                float scale;
                if (ratio <= 0.7) {
                    //放大1.2倍
                    scale = ratio / 0.7f * 0.2f + 1;
                } else {
                    scale = 1.2f - ((ratio - 0.7f) / 0.3f) * 0.2f ;
                }
                mTvTip.setScaleX(scale);
                mTvTip.setScaleY(scale);
            }
        });
        enlarge.start();
    }

    private FaceHolder getFaceNearestFromCenter(List<Rect> facesList) {
        double minDist = Math.max(DeviceUtils.getScreenWidthPx(), DeviceUtils.getScreenHeightPx());
        double dist;
        int index = 0;
        for (int i = 0; i < facesList.size(); i++) {
            Rect face = facesList.get(i);
            dist = getFaceDistFromMaskCenter(face);
            if (dist < minDist) {
                minDist = dist;
                index = i;
            }
        }
        Rect f = facesList.get(index);
        boolean isInRequireRange = checkFaceRange(f);
        if (!isInRequireRange) return null;
        return new FaceHolder(index, facesList.get(index));
    }

    private double getFaceDistFromMaskCenter(Rect face) {
        Point faceCenterPt = new Point(face.centerX(), face.centerY());
        Point maskCenterPt = new Point(mFaceMaskRect.centerX(), mFaceMaskRect.centerY());
        double diff = Math.pow(faceCenterPt.x - maskCenterPt.x, 2) + Math.pow(faceCenterPt.y - maskCenterPt.y, 2);
        diff = Math.sqrt(diff);
        return diff;
    }

    private boolean checkFaceRange(Rect face) {
        if (!Rect.intersects(face, mFaceMaskRect)) {
            mNewDetectState = DETECT_STATE_FACE_POSITION_ERROR;
            return false;
        }

        mIntersectHelpRegion.set(face);
//        if (!TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
            mIntersectRegion.setPath(mFaceMaskPath, mIntersectHelpRegion);
//        } else {
//            mIntersectRegion.setPath(mFaceVisualPath, mIntersectHelpRegion);
//        }
        int area = Utils.calculateRegionArea(mIntersectRegion);
        if ((float)area / (face.width() * face.height()) > SHARE_AREA_THRESHOLD) {
//            if (!TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
                if ((float) face.width() * face.height() / (mFaceMaskRect.width() * mFaceMaskRect.height()) > SHARE_AREA_MIN_THRESHOLD) {
                    mNewDetectState = DETECT_STATE_READY;
                    return true;
                } else {
                    // 人脸框太小，提示错误
                    mNewDetectState = DETECT_STATE_FACE_TOO_SMALL;
                    return false;
                }
//            }
//            else {
//                if ((float) face.width() * face.height() / (mFaceMaskHeight * mFaceMaskHeight) > FaceScanActivity.SHARE_AREA_MIN_THRESHOLD2) {
//                    mNewDetectState = DETECT_STATE_READY;
//                    return true;
//                } else {
//                    // 人脸框太小，提示错误
//                    mNewDetectState = DETECT_STATE_FACE_TOO_SMALL;
//                    return false;
//                }
//            }
        }
        mNewDetectState = DETECT_STATE_FACE_POSITION_ERROR;
        return false;
    }

    private void setCurSelectFaceFromMultipleFaces(FaceHolder curFace) {
        mCurSelectFace = curFace;
    }

    private boolean checkFaceIntersectAreaRate(float intersectS, float faceS, float threshold) {
        return (intersectS / faceS) > threshold;
    }

    private boolean isDetectStateChange() {
        return mCurDetectState != mLastDetectState;
    }

    private void showBottomTip(SpannableString tip, boolean replaceTip) {
        if (mTvTip.getVisibility() == View.INVISIBLE) {
            mTvTip.setVisibility(View.VISIBLE);
            mTvTip.setText(tip);
            getTipShowAnimator().start();
            return;
        }
        if (mTvTip.getVisibility() == View.VISIBLE && replaceTip) {
            mTvTip.setText(tip);
            getTipShowAnimator().start();
            return;
        }
    }

    private ValueAnimator getTipShowAnimator() {
        if (mTipShowAnimator == null) {
            mTipShowAnimator = ValueAnimator.ofFloat(0, 1f);
            mTipShowAnimator.setDuration(TIP_SHOW_ANIM_TIME);
            mTipShowAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float ratio = animation.getAnimatedFraction();
                    mTvTip.setAlpha(ratio);
                    float translationY = mTipHeight - ratio * mTipHeight;
                    mTvTip.setTranslationY(translationY);
                }
            });
        }
        return mTipShowAnimator;
    }

    @Override
    public void onFaceRefresh(float left, float top, float right, float bottom) {
        //照片调整后，人脸框位置刷新回调
        if (mFaceRect == null) return;
        mFaceRect.set((int) left, (int) top, (int) right, (int) bottom);
        DLog.d(TAG, "face position refresh: " + mFaceRect);
//        mDrawFaceView.refresh((int) left, (int) top, (int) right, (int) bottom);
    }

    @Override
    public void onFaceListRefresh(List<RectF> list) {
        if (mFaceRectList == null || mFaceRectList.size() == 0) return;
        RectF dst;
        Rect src;
        for (int i = 0; i < list.size(); i++) {
            src = mFaceRectList.get(i);
            dst = list.get(i);
            src.set((int) dst.left, (int) dst.top, (int) dst.right, (int) dst.bottom);
        }
//        mDrawFaceView.refresh(mFaceRectList);
    }

    @Override
    public void onFaceRefreshEnd() {
        if (mFaceRect != null) processSingleFaceRect(mFaceRect);
//        if (!TextUtils.equals(mAction, ACTION_AGING_SCANNER)) {
            if (mFaceRectList != null) processMultipleFaceRect(mFaceRectList);
//        } else {
//            if (mFaceRectList != null && !mFaceRectList.isEmpty()) {
//                //逐个检查，只要有一张脸符合要求，就通过
//                int size = mFaceRectList.size();
//                for (int i=0; i<size; i++) {
//                    Rect face = mFaceRectList.get(i);
//                    if (checkFaceRange(face)) {
//                        //通过
//                        DLog.d("detectLog", "第" + i + "张脸通过");
//                        processDetectResult(mNewDetectState);
//                        break;
//                    } else {
//                        DLog.d("detectLog", "第" + i + "张脸不通过");
//                    }
//                }
//                processDetectResult(mNewDetectState);
//                //不通过
//            }
//        }
    }

    public Rect adjustBoundingBox(Rect rect) {
        Rect ret = new Rect(rect);
        ret.left /= mBoundingBoxScale;
        ret.top /= mBoundingBoxScale;
        ret.right /= mBoundingBoxScale;
        ret.bottom /= mBoundingBoxScale;
        return ret;
    }

    private boolean mIsFirstTimeDetectFaceSuccess = true;

    @Override
    public void onDetectFaceSuccess(final @NonNull List<FirebaseVisionFace> results) {
        // 人脸框识别成功回调
        // 耗时操作，不要多次调用
        // 只在Activity初始化时调用一次
        DLog.d(TAG, "onDetectFaceSuccess");
        if (mIsFirstTimeDetectFaceSuccess) {//修复可能的线上crash
            mIsFirstTimeDetectFaceSuccess = false;
            if (isFinishing()) return;
            if (mLayoutAdjust == null) return;
            mLayoutAdjust.post(new Runnable() {
                @Override
                public void run() {
                    mAdjustView.setCanTouch(true);
                    showLoadingView(false);
                    processDetectFaceResult(results);
                }
            });
        } else {
            processDetectFaceResult(results);
        }
    }

    @Override
    public void onDetectFaceFailure(@NonNull Exception e) {
        // 人脸框识别异常回调
        DLog.d(TAG, "onDetectFaceFailure");
        if (isFinishing()) return;
        if (mLayoutAdjust == null) return;
        mLayoutAdjust.post(new Runnable() {
            @Override
            public void run() {
                mAdjustView.setCanTouch(true);
                showLoadingView(false);
                mNewDetectState = DETECT_STATE_NO_FACE;
                processDetectResult(mNewDetectState);
            }
        });
        mFaceRectList = null;
        mFaceRect = null;
    }

    @Override
    public void onDetectFaceLandmarkSuccess(@NonNull List<FirebaseVisionFace> results) {
        // 人脸坐标点识别成功回调
        DLog.d(TAG, "onDetectFaceLandmarkSuccess");
    }

    @Override
    public void onDetectFaceLandmarkFailure(@NonNull Exception e) {
        // 人脸坐标点识别失败回调
        DLog.d(TAG, "onDetectFaceLandmarkFailure");
    }

    public static class FaceHolder {
        public int index;
        public FirebaseVisionFace face;
        public Rect faceRect;

        FaceHolder() {
            index = -1;
            face = null;
            faceRect = null;
        }

        FaceHolder(int ind, FirebaseVisionFace f) {
            index = ind;
            face = f;
        }

        FaceHolder(int ind, Rect f) {
            index = ind;
            face = null;
            faceRect = new Rect(f);
        }
    }
}
